package com.swyc.osschat.Test.designMode.prototype.run;

import com.swyc.osschat.Test.designMode.prototype.impl.Param;
import com.swyc.osschat.Test.designMode.prototype.impl.Wife;
import com.swyc.osschat.Test.designMode.prototype.impl.Wife2;

/**
 * @description Java 原型模式
 * 一、简介
 *  用一个已经创建的实例作为原型，通过复制改原型对象来创建一个和原型对象相同的新对象。原型模式是创建型模式的一种，主要用于创建重复的对象，
 *  主要角色：
 *      抽象原型类：规定具体原型对象必须实现的clone()方法。
 *      具体原型类：实现抽象原型的clone()方法。
 *      访问类：使用具体原型类的clone()方法复制出新的对象。
 * 二、实现
 *  原型模式可以分为浅克隆和深克隆：
 *      浅克隆：创建一个新对象，新对象的属性和原对象完全相同，但是非基本数据类型，仍指向原有属性对象的内存地址。
 *      深克隆：创建一个新对象，属性中的对象也会被克隆，不指向原对象的内存地址。
 * @Author: z156940l@outlook.com
 * @className Test
 * @Date: 2022/7/25 18:15
 */
public class Test {
    public static void main(String[] args) {
        try {
            test1();
            test2();
        }catch (CloneNotSupportedException e){
            //TODO
        }
    }

    /**
     * 浅克隆
     * 举例：
     * 比如我有一个老婆，这个老婆身材完美，前凸后翘，但是一个老婆满足不了我，我想多要一个一模一样的老婆，此时可以通过原型模式复制出新的老婆。
     * java的Object类中提供了clone()方法来实现克隆，Cloneable接口是指上面说到的抽象原型类，所以我们使用Cloneable当作抽象原型类。
     * 此时通过原型模式（浅拷贝）就创建出了我的第二个身高不同老婆。非常满意。
     * @throws CloneNotSupportedException
     */
    private static void test1() throws CloneNotSupportedException {
        //创建原型对象
        Wife wife = new Wife();
        //通过原型对象创建新对象
        Wife wife2 = wife.clone();
        //要一个大一些的
        wife2.setHeight(170);
        System.out.println(wife.toString());
        System.out.println(wife2.toString());
    }

    /**
     * 为了验证深浅克隆的区别，我们把Wife中的参数封装成对象试试看。
     * 为什么只修改了wife2的身高，wife的身高也变了呢？这怎么行，原因就是因为目前还是浅克隆，
     * 写这段代码就是为了验证深浅克隆，可以看出 wife中的params只要修改了一个，就都会发生变化，
     * 可见两个param所指向的内存地址还是相同的。解决办法就是深克隆。
     * 深克隆实现：
     * 深克隆可以使用流的方式来实现，只需要在原型类中的clone方法中来实现即可。
     * 此时通过原型模式的深克隆就得到了两个身高不一样的老婆。
     * @throws CloneNotSupportedException
     */
    private static void test2() throws CloneNotSupportedException {
        //创建原型对象
        Wife2 wife = new Wife2();
        //设置属性
        wife.setParam(new Param(20,165));

        //通过原型对象创建新对象
        Wife2 wife2 = wife.clone();
        //修改新对象的身高
        wife2.getParam().setHeight(170);
        System.out.println(wife.getParam().toString());
        System.out.println(wife2.getParam().toString());
    }
}
